<?php

namespace App\Http\Controllers;

use Exception;
use App\Models\User;
use App\Models\Project;
use App\Jobs\Push\DeleteTag;
use Illuminate\Http\Request;
use App\Models\System\SysLog;
use App\Jobs\Push\AddUserTags;
use App\Jobs\Push\RemoveUserTags;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Facades\Excel;
use App\Repositories\CompanyRepository;
use App\Repositories\ProjectRepository;
use Illuminate\Database\Eloquent\Builder;
use Maatwebsite\Excel\Writers\CellWriter;
use Maatwebsite\Excel\Writers\LaravelExcelWriter;
use App\Http\Requests\Logic\Project\QueryResource;
use App\Http\Requests\Logic\Project\StoreResource;
use App\Http\Requests\Logic\Project\UpdateResource;
use App\Http\Requests\Logic\Project\DestroyResource;
use App\Http\Requests\Logic\Project\QueryCollection;
use Maatwebsite\Excel\Classes\LaravelExcelWorksheet;

/**
 * 项目管理控制器
 *
 * Date: 22/03/2018
 * @author George
 * @package App\Http\Controllers
 */
class ProjectController extends Controller
{
	protected $projectRepository;
	protected $companyRepository;

	/**
	 * ProjectController constructor.
	 * @param ProjectRepository $projectRepository
	 * @param CompanyRepository $companyRepository
	 */
	public function __construct(
		ProjectRepository $projectRepository,
		CompanyRepository $companyRepository
	)
	{
		$this->projectRepository = $projectRepository;
		$this->companyRepository = $companyRepository;
	}

	/**
	 * 获取项目数据或导出Excel
	 *
	 * Date: 2018/5/24
	 * @author George
	 * @param QueryCollection $request
	 * @return \Illuminate\Http\JsonResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
	 */
	public function index(QueryCollection $request)
	{
		$address = $request->get('address');
		$project_name = $request->get('project_name');
		$paginate = $request->get('paginate', 15);
		$export = $request->get('export');

		$query = DB::table('projects')->select([
			'projects.id', 'projects.company_id', 'projects.name', 'projects.address',
			'radius', 'cover', 'projects.longitude', 'projects.latitude'
		])->where('company_id', Auth::user()->company_id);

		if ($address) {
			$query->where('projects.address', 'like', "%{$address}%");
		}

		if ($project_name) {
			$query->where('projects.name', 'like', "%{$project_name}%");
		}

		/**
		 * 导出数据
		 */
		if ($export) {
			SysLog::log(Auth::user(),'项目模块','导出项目数据');
			Excel::create('projects', function ($excel) use ($query) {
				/**
				 * @var LaravelExcelWriter $excel
				 */
				$excel->sheet('项目列表', function($sheet) use ($query) {
					/**
					 * 设置列宽度
					 * @var LaravelExcelWorksheet $sheet
					 */
					$sheet->setWidth(array(
						'A'     =>  5,
						'B'     =>  20,
						'C'     =>  40,
						'D'     =>  8,
					));

					/**
					 * 设置对其方式
					 */
					$sheet->cells('A:D', function($cells) {
						/**
						 * @var CellWriter $cells
						 */
						$cells->setAlignment('center');
					});

					$sheet->fromArray($query->get()->map(function ($item) {
						return [
							'ID'=> $item->id,
							'项目名称' => $item->name,
							'项目地址' => $item->address,
							'考勤范围' => $item->radius,
						];
					}));
				});
			})->download('xlsx');
        }

		return success($query->paginate($paginate));
	}

	/**
	 * 获取指定项目详情
	 *
	 * Date: 11/04/2018
	 * @author George
	 * @param QueryResource $request
	 * @param Project $project
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function show(QueryResource $request, Project $project)
	{
		$date = $request->get('date');
		$start = $request->get('start');
		$end = $request->get('end');

		$query = $project->demands();

		$query->when($date, function ($query, $date) {
			/**
			 * @var Builder $query
			 */
			return $query->where('date', $date);
		});

		if ($start && $end) {
			$query->whereBetween('date', [$start, $end]);
		}

		$project->demands = $query->get();

		return success($project);
	}

	/**
	 * 创建项目
	 *
	 * Date: 11/04/2018
	 * @author George
	 * @param StoreResource $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \App\Exceptions\GeneralException
	 */
	public function store(StoreResource $request)
	{
		$attributes = $this->extractInputFromRules($request, $request->rules());
		$project = $this->projectRepository->create($attributes);
        SysLog::log(Auth::user(),'项目模块','创建项目');
        return stored($project);
	}

	/**
	 * 更新项目
	 *
	 * Date: 11/04/2018
	 * @author George
	 * @param UpdateResource $request
	 * @param Project $project
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function update(UpdateResource $request, Project $project)
	{
		$attributes = $this->extractInputFromRules($request, $request->rules());
		$project->update($attributes);
        SysLog::log(Auth::user(),'项目模块','更新项目信息');
        return updated($project);
	}

	/**
	 * 删除项目
	 *
	 * Date: 11/04/2018
	 * @author George
	 * @param DestroyResource $request
	 * @param Project $project
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Exception
	 */
	public function destroy(DestroyResource $request, Project $project)
	{
		$force = $request->get('force');
		$force ? $project->delete() : $project->forceDelete();
        SysLog::log(Auth::user(),'项目模块','删除项目');
        // 分发删除标签任务，异步调用JPUSH 删除标签API
        dispatch(new DeleteTag("project_{$project->id}"));
        return deleted();
	}

	/**
	 * 项目添加人员
	 *
	 * Date: 15/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 * @throws \Throwable
	 */
	public function attach(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'user_id' => 'required',
		]);
		$project_id = $request->get('project_id');
		$user_id = $request->get('user_id');

		try {
			/**
			 * @var User $user
			 */
			$user = User::findOrFail($user_id);
			if ($user->project_id == 0) {
				$user->project_id = $project_id;
				$user->saveOrFail();
				return success($user);
			}
			/**
			 * 分发绑定用户通知 Tag 的任务
			 */
			dispatch(new AddUserTags($user, "project_{$project_id}"));
			$project = $user->project;
			$message = $project ? '该人员已分配到：' . $project->name . ' 项目' : '其他项目';
            SysLog::log(Auth::user(),'项目模块','添加人员到项目');
			return failed($message);
		} catch (Exception $exception) {
			return internalError('添加人员失败');
		}
	}

	/**
	 * 从项目移除人员
	 *
	 * Date: 10/05/2018
	 * @author George
	 * @param Request $request
	 * @return \Illuminate\Http\JsonResponse
	 */
	public function detach(Request $request)
	{
		$this->validate($request, [
			'project_id' => 'required',
			'user_id' => 'required',
		]);

		try {
			$project_id = $request->get('project_id');
			$user_id = $request->get('user_id');
			DB::table('users')
				->where('id', $user_id)
				->where('project_id', $project_id)
				->update(['project_id' => 0]);
			/**
			 * @var User $user
			 */
			$user = User::findOrFail($user_id);
			SysLog::log(Auth::user(), '项目模块', '从项目移除人员');
			dispatch(new RemoveUserTags($user, "project_{$project_id}"));
			return deleted('移除人员成功');
		} catch (Exception $exception) {
			return internalError('移除人员失败');
		}
	}
}
